package com.pic.mgt.telnetd;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;

import com.pic.mgt.log.IgxLog;

public abstract class AbstractCommandPerformer implements CommandPerformer {
	protected final int COMMAND_PERFORM_SUCCESS_CODE = 0;
	protected final int COMMAND_PERFORM_FAILED_CODE = 1;
	
	private Options options;
	
	private boolean isCurrentPerforming = false;
	
	private final String helpParamName = "help";
	
	public AbstractCommandPerformer() {
		options = new Options();
		
		// 增加 help 參數
		this.options.addOption(this.helpParamName, false, "display parameter description.");
		
		// (給子類)新增其它參數
		addOption(this.options);
	}
	
	@Override
	public String performCommand(CommandLine commandLine) {
		this.isCurrentPerforming = true;
		
		if (commandLine.hasOption(this.helpParamName)) {
			// 表示是要查詢指令的參數說明
			
			StringWriter stringWriter = new StringWriter();
			PrintWriter printWriter = new PrintWriter(stringWriter);
			
			HelpFormatter formatter = new HelpFormatter();
			formatter.printHelp(printWriter, 80, getCommandName(), "", this.options, 3, 8, "", true);
			
			try {
				// throws IOException
				stringWriter.close();
				printWriter.close();
			} catch (IOException e) {
				// 基本上不太可能會發生
				
				// ********************** Log **********************
				IgxLog.messageLog.error(this,
								"SUDA-311 Processing shell command '{}' failed in generating help description.",
								this.getCommandName());
				// ********************** Log **********************
				
				this.isCurrentPerforming = false;
				
				return getReplyMessageWithReplyCode(
								getDefaultCommandPerformFailedReplyMessage(),
								COMMAND_PERFORM_FAILED_CODE);
			}
			
			this.isCurrentPerforming = false;
			
			return getReplyMessageWithReplyCode(stringWriter.toString(),
												COMMAND_PERFORM_SUCCESS_CODE);
		}
		else {
			// 交由子類做指令執行動作，並回傳結果訊息(內包含 reply code)
			
			String replyMessageWithReplyCode = doCommandPerform(commandLine);
			
			this.isCurrentPerforming = false;
			
			return replyMessageWithReplyCode;
		}
	}
	
	@Override
	public boolean isCurrentPerforming() {
		return isCurrentPerforming;
	}
	
	protected String getReplyMessageWithReplyCode(String replyMessage, int replyCode) {
		return
			String.valueOf(replyCode) + " " + replyMessage;
	}
	
	protected String getDefaultCommandPerformFailedReplyMessage() {
		return
			"Command '" + getCommandName() + "' execution failed.";
	}
	
	protected String getCommandPerformFinishMsg() {
		return
			getReplyMessageWithReplyCode(
					"Sending command to execution completed.",
					this.COMMAND_PERFORM_SUCCESS_CODE);
	}
	
	protected String getCommandPerformFailedMsg() {
		return
			getReplyMessageWithReplyCode(
					"Sending command to execution occured an error.",
					this.COMMAND_PERFORM_FAILED_CODE);
	}
	
	@Override
	public Options getCommandOptions() {
		return this.options;
	}
	
	/**
	 * 做指令的執行動作，並回傳執行結果訊息。
	 * @param commandLine
	 * @return
	 */
	protected abstract String doCommandPerform(CommandLine commandLine);
	
	/**
	 * 新增參數
	 * @param options
	 */
	protected abstract void addOption(Options options);
}
